Raycaster射線法,是指在場景中打出一條射線,紀錄打出去的射線所有經過的網格,並且計算出與三角網格的交點,若沒有經過任何網格則不進行網格的紀錄。
在CAD軟體的應用中,如何找到點選的對象是個基本且重要的問題,下圖是表示空間中的一群網格資料,並在空間中打出一條藍色的射線,紅色的點表示射線經過網格的位置。
一條射線經過了網格
首先在宣告區增加intersects用來存放取得的資料點。
this.intersects = [];
接著在init加入兩個監聽式mousedown、mouseup並指向兩個函數onMouseDown、onMouseUp。
//滑鼠設定
self.container.addEventListener('mousedown', self.onMouseDown.bind(self), false);
self.container.addEventListener('mouseup', self.onMouseUp.bind(self), false);
然後要注意到TrackballControls的第二個參數需要使用的是container,這裡需要修正一下否則會點選不到container。
self.controls = new TrackballControls(
self.camera,
self.container
);
再建立一個滑鼠點選時的onMouseDown事件的函數,其中透過JavaScript內建函數取得mouse的座標,並且從相機去設定raycaster與滑鼠的關係,再透過intersectObjects取得目前場景中所有射線打中的物件。若有打中空間中物件,intersects的陣列就會有複數以上的資料。
Viewer.prototype.onMouseDown = function (event) {
var self = this;
self.mouse.x = (event.clientX / window.innerWidth ) * 2 - 1;
self.mouse.y = - (event.clientY / window.innerHeight ) * 2 + 1;
self.raycaster.setFromCamera(self.mouse, self.camera);
self.intersects = self.raycaster.intersectObjects(self.scene.children);
//Do Something
};
值得注意的是為了在我們點選的過程中讓TrackballControls停止作用,要給controls.enabled一個false的布林值來暫時關閉,這樣滑鼠點選到物件後就不會有旋轉平移的功能。
if (self.intersects.length > 0) {
self.controls.enabled = false;
//Draw Something
}
本文做一個簡單的應用,在點選的位置畫出一顆球,使用先前教過的語法就能輕鬆完成囉,順帶一提要在meshs也push球的資訊,才能在Clear的時後也把球給一併清除掉。
var geometry = new THREE.SphereBufferGeometry(0.5, 16, 16);
var material = new THREE.MeshPhongMaterial({
color: 0xff0000
});
var mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(self.intersects[0].point);
self.scene.add(mesh);
self.meshs.push(mesh);
最後還要建立一個onMouseUp函數,用來在放開滑鼠後能夠將TrackballControls給從新啟用回來,下圖是本次的繪圖結果。
Viewer.prototype.onMouseUp = function (event) {
var self = this;
self.controls.enabled = true;
};
在monkey.stl上面畫圓球
https://github.com/QQBoxy/threecad/blob/master/client/example7/Viewer.js
這次介紹了一個建立CAD軟體所需的選擇功能,在後續的範例中將會大量的使用此語法,此方法很重要大家務必要學會使用喔。